package windows
{
	import flash.desktop.NativeProcess;
	import flash.desktop.NativeProcessStartupInfo;
	import flash.events.NativeProcessExitEvent;
	import flash.events.ProgressEvent;
	import flash.filesystem.File;
	import flash.utils.clearTimeout;
	import flash.utils.setTimeout;

	import mx.controls.Alert;

	public class WinCmd
	{

		/** 输入流字符 */
		public var charSetInput:String="gb2312";
		/** 输出流字符 */
		public var charSetOutput:String="gb2312";

		public var onWaitingOpen:Function;
		public var onWaitingClose:Function;
		/** 当前接收条数onWaitingCount(count:int) */
		public var onWaitingCount:Function;
		/** 接收原始数据onOutData(data:String) */
		public var onOutData:Function;

		//本机进程
		private var process:NativeProcess;

		//cmd相关
		private var outIndex:int;
		private var outCount:int;
		private var runTagCmd:String=null;
		private var runTagFunclist:Object={};
		private var runTagDelaylist:Object={};
		private var runTagDatalist:Object={};
		private var timeOutIndex:int=0;

		public function WinCmd():void
		{
			trace("################################################");
			trace("欢迎使用NativeProcess本机进程Windows CMD封装类。");
			trace("使用initNativeProcess(cmd.exe)方法初始化CMD进程。");
			trace("################################################");
		}

		public function initNativeProcess(cmdExePath:String="c:\\windows\\system32\\cmd.exe", complete:Function=null):void
		{
			if (NativeProcess.isSupported == false)
			{
				Alert.show("当前环境不支持Windows CMD本机进程!\n请尝试将项目app.xml修改为以下信息\n<supportedProfiles>extendedDesktop desktop</supportedProfiles>", "提示信息\t\t\t\t\t\t\t\t\t\t\t");
				return;
			}
			var cmdexefile:File=new File(cmdExePath);
			if (cmdexefile.exists == false)
			{
				Alert.show("本机位置不存在！\n" + cmdExePath);
				return;
			}
			var info:NativeProcessStartupInfo=new NativeProcessStartupInfo(); //启动参数
			info.executable=cmdexefile;
			var processArg:Vector.<String>=new Vector.<String>();
			//processArg[0]=""; 
			//processArg[1]="";
			info.arguments=processArg;
			process=new NativeProcess();
			process.addEventListener(NativeProcessExitEvent.EXIT, packageOverHandler);
			process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, onError);
			process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, outputHandler);
			process.start(info);
			if (complete != null)
			{
				complete();
			}
		}

		protected function packageOverHandler(event:NativeProcessExitEvent):void
		{
		}

		protected function onError(event:ProgressEvent):void
		{
			var pro:NativeProcess=event.target as NativeProcess;
			var data:String=pro.standardOutput.readMultiByte(pro.standardOutput.bytesAvailable, charSetOutput);
		}

		protected function outputHandler(event:ProgressEvent):void
		{
			var pro:NativeProcess=event.target as NativeProcess;
			var data:String=pro.standardOutput.readMultiByte(pro.standardOutput.bytesAvailable, charSetOutput);
			//输出原始
			if (onOutData != null)
			{
				onOutData(data);
			}
			//寻找命令
			for (var cmd:String in runTagFunclist)
			{
				if (data.indexOf(cmd) != -1)
				{
					var callback:Function=runTagFunclist[cmd] as Function;
					if (callback != null && runTagCmd != cmd)
					{
						runTagCmd=cmd;
						runTagDatalist[cmd]="";
						openWaitingWindow();
						outCount=0;
						trace("WINCMD==>[√]", cmd);
					}
					else
					{
						trace("WINCMD==>[×]", cmd);
						deleteCmd(cmd);
					}
					//命令行不处理
					return;
				}
			}
			//如果不是命令那就是结果
			data=data.replace(/^[A-Z]:\\.*\>$/mg, "");
			if (runTagCmd)
			{
				callback=runTagFunclist[runTagCmd] as Function;
				if (callback != null)
				{
					runTagDatalist[runTagCmd]+=data;
					onWaitingCountMessage(outCount); //收到条数
					outCount++;
					//trace("---->", outCount);
					//等待下一条时间
					var delay:int=int(runTagDelaylist[runTagCmd]);
					if (delay < 100)
					{
						delay=100;
					}
					//超时处理
					clearTimeout(timeOutIndex);
					timeOutIndex=setTimeout(function():void
					{
						deleteCmd(runTagCmd);
						runTagCmd=null;
						closeWaitingWindow();
						Alert.show("数据请求超时或服务无响应！", "提示信息");
					}, delay + 2000);
					//拉取数据
					clearTimeout(outIndex);
					outIndex=setTimeout(function():void
					{
						clearTimeout(timeOutIndex);
						var outdata:String=runTagDatalist[runTagCmd];
						callback(runTagCmd, outdata);
						deleteCmd(runTagCmd);
						runTagCmd=null;
						closeWaitingWindow();
					}, delay);
				}
			}
		}

		/**
		 * 执行cmd命令
		 * @param cmd    标准CMD命令
		 * @param func   回调响应方法
		 * @param delay  接收输出数据等待时间
		 *
		 */
		public function runCmd(cmd:String, func:Function=null, delay:int=200):void
		{
			runTagFunclist[cmd]=func;
			runTagDatalist[cmd]="";
			runTagDelaylist[cmd]=delay;
			process.standardInput.writeMultiByte(cmd + "\n", charSetInput);
		}

		private function deleteCmd(cmd:String):void
		{
			delete runTagFunclist[cmd];
			delete runTagDatalist[cmd];
			delete runTagDelaylist[cmd];
		}

		private function openWaitingWindow():void
		{
			if (onWaitingOpen != null)
			{
				onWaitingOpen();
			}
		}

		private function onWaitingCountMessage(count:int):void
		{
			if (onWaitingCount != null)
			{
				onWaitingCount(count);
			}
		}

		private function closeWaitingWindow():void
		{
			if (onWaitingClose != null)
			{
				onWaitingClose();
			}
		}

	}
}
